import scripting.Vm;
import scripting.VmLua;
import scripting.VmPython;
import scripting.DateObject;
import scripting.Dictionary;
import haxe.io.Bytes;

class Test {

	public static function main() {
		new LuaTest().run();
		new PythonTest().run();
	}
}

class PythonTest extends LuaTest
{
	public function new() {
		super();
		vm = new VmPython();
//http://www.python.org/doc/2.3.5/inst/search-path.html
// 		vm.setPaths(["./"]);
// 		trace(vm.execFile("test.py"));

		var res : Dynamic = null;
		try {
			res = vm.execFile("test.py");
		} catch(e:Dynamic) {
			throw(vm.getError());
		}
		if(res != null) {
			var t = Type.typeof(res);
			throw "Invalid init value returned from test.py " + t + " " + res;
		}
	}

	public override function createVm() : Vm {
		return new VmPython();
	}

	/**
	* Add dynamic code
	**/
	public override function testTwo() {
		vm.exec("print '*** FROM "+neko.Sys.systemName()+" PYTHON *** Second module';\ndef bar(a,b):\n\tprint '---- testBar';\n\treturn a*b;\n\n");

		var res = vm.call("bar", [2,3]);
		if(res != 6)
			throw "Invalid answer " + res;

		var res = vm.call("foo", [1,2]);
		if(res != 3)
			throw "Invalid answer " + res;
	}

	public override function testFive(){}
	public override function testSix() {}
}

class LuaTest
{
	var vm : Vm;

	public function new() {
		if(Type.getClassName(Type.getClass(this)) == "LuaTest") {
			vm = new VmLua(false);
			vm.loadStdLibs(["base","table","string","math","os","package"]);
			vm.setPaths(["./"]);
			var res = vm.execFile("test.lua");
			if(res != 256) {
				var t = Type.typeof(res);
				throw "Invalid init value returned from test.lua " + t + " " + res;
			}
		}
	}

	public function createVm() : Vm {
		var v = new VmLua(true);
		v.setPaths(["./"]);
		return v;
	}

	public function run() {
		trace("VM VERSION: " + vm.version);
		testOne();
		testTwo();
		testThree();
		testFour();
		testFive();
		testSix();
		testSeven();
		testEight();
		testNine();
	}

	public function testOne() {
		var res = vm.call("foo", [1,2]);
		if(res != 3)
			throw "Invalid answer " + res;
	}

	/**
	* Add dynamic code
	**/
	public function testTwo() {
		vm.exec("print '*** FROM "+neko.Sys.systemName()+" LUA *** Second module'; function bar(a,b) print '---- testBar'; return a*b end;");

		var res = vm.call("bar", [2,3]);
		if(res != 6)
			throw "Invalid answer " + res;

		var res = vm.call("foo", [1,2]);
		if(res != 3)
			throw "Invalid answer " + res;
	}

	public function testThree() {
		var res = vm.call("testString", ["testing"]);
		if(res != "response")
			throw "Bad response : " + res;
	}

	public function testFour() {
		var res = vm.call("testArray", [["testing",1,2.0,3]]);
		trace(res);
	}

	/**
	* Anon object test
	**/
	public function testFive() {
		var o : Dynamic = {}
		o.foo = "1";
		o.bar = 2;
		var res = vm.call("testObject", [o]);
	}

	/**
	* Tests lua's multiple return value mode.
	**/
	public function testSix() {
		cast(vm, VmLua).multiReturnMode = true;
		var res = vm.call("testMultiReturn", []);
		trace(res);
		cast(vm, VmLua).multiReturnMode = false;
	}

	/**
	* Dictionary class test
	**/
	public function testSeven() {
		var o = new Dictionary();
		o.set("foo", "1");
		o.set(2, "bar");
		o.set(3.5, "Three point five");
		var res = vm.call("testDict", [o]);
		var d = cast(res, Dictionary);
		if(d.get("darwin") != 1)
			throw "Bad Darwin score";
		if(d.get("religion") != 0)
			throw "Bad religion score";
	}

	/**
	* Date test
	*/
	public function testEight() {
		var d = vm.call("testDate", [DateObject.convert(Date.now())]);
		trace(DateObject.convert(d));
	}

	/**
	* Second VM test
	**/
	public function testNine() {
		var vm2 = createVm();
		try {
			vm2.call("foo", [1,2]);
			throw "Foo() should not exist in vm2";
		} catch(e:Dynamic) {}

		try {
			vm.call("foo", [1,2]);
		} catch(e:Dynamic) {
			throw "Foo() should still exists in vm";
		}
	}
}
